package com.zt.dao.base.impl;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.BatchPreparedStatementSetter;
import org.springframework.jdbc.core.CallableStatementCallback;
import org.springframework.jdbc.core.CallableStatementCreator;
import org.springframework.jdbc.core.ConnectionCallback;
import org.springframework.jdbc.core.PreparedStatementCallback;
import org.springframework.jdbc.core.PreparedStatementCreator;
import org.springframework.jdbc.core.PreparedStatementSetter;
import org.springframework.jdbc.core.ResultSetExtractor;
import org.springframework.jdbc.core.RowCallbackHandler;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.SqlParameter;
import org.springframework.jdbc.core.StatementCallback;
import org.springframework.jdbc.core.support.JdbcDaoSupport;
import org.springframework.jdbc.support.KeyHolder;
import org.springframework.jdbc.support.nativejdbc.NativeJdbcExtractor;
import org.springframework.jdbc.support.rowset.SqlRowSet;

import com.zt.action.utils.Constans;
import com.zt.dao.support.Page;

public class BaseJdbcSupport extends JdbcDaoSupport {

	/**
	 * 方法 pagingFind
	 * 
	 * @param sql
	 * @param start
	 * @param limit
	 * @param rowMapper
	 * @return 分页查询返回PageInfo (分页内的数据对象List 和 总数据数)
	 */
	@SuppressWarnings("unchecked")
	public <X> Page<X> pagingFind(String sql, long start, long limit,
			RowMapper rowMapper) {
		return pagingFind(sql, start, limit, rowMapper, new Object[] {});
	}

	
	/**
	 * 方法 pagingFind
	 * 
	 * @param sql
	 * @param start
	 * @param limit
	 * @param rowMapper
	 * @return 分页查询返回PageInfo (分页内的数据对象List 和 总数据数)
	 */
	@SuppressWarnings("unchecked")
	public <X> Page<X> pagingFind(Page<X> pi,String sql, long start, long limit,
			RowMapper rowMapper) {
		return pagingFind(pi,sql, start, limit, rowMapper, new Object[] {});
	}
	
	/**
	 * 方法 pagingFind
	 * 
	 * @param sql
	 * @param start
	 * @param limit
	 * @param rowMapper
	 * @param obj
	 * @return 单条件分页查询返回PageInfo (分页内的数据对象List 和 总数据数)
	 */
	@SuppressWarnings("unchecked")
	public <X> Page<X> pagingFind(String sql, long start, long limit,
			RowMapper rowMapper, Object obj) {
		try {
			Page<X> pi = new Page<X>();
			pi.setTotalCount(this.pagingFindCount(sql, obj));
			pi.setResult((List<X>) this.pagingFindList(sql, start, limit,
					rowMapper, obj));
			return pi;
		} catch (RuntimeException e) {
			this.logger.error("JDBC分页查询时出错！");
			throw e;
		}
	}

	/**
	 * 方法 pagingFind
	 * @param <X>
	 * @param pi
	 * @param sql
	 * @param start
	 * @param limit
	 * @param rowMapper
	 * @param obj
	 * @return 分页查询返回PageInfo (分页内的数据对象List 和 总数据数)
	 */
	@SuppressWarnings("unchecked")
	public <X> Page<X> pagingFind(Page<X> pi,String sql, long start, long limit,
			RowMapper rowMapper, Object[] obj) {
		try {
			pi.setStartNo(start);
			pi.setTotalCount(this.pagingFindCount(sql, obj));
			pi.setResult((List<X>) this.pagingFindList(sql, start, limit,
					rowMapper, obj));
			return pi;
		} catch (RuntimeException e) {
			this.logger.error("JDBC分页查询时出错！");
			throw e;
		}
	}
	
	
	/**
	 * 方法 pagingFind
	 * 
	 * @param sql
	 * @param start
	 * @param limit
	 * @param rowMapper
	 * @param obj
	 * @return 按条件分页查询返回PageInfo (分页内的数据对象List 和 总数据数)
	 */
	@SuppressWarnings("unchecked")
	public <X> Page<X> pagingFind(String sql, long start, long limit,
			RowMapper rowMapper, Object[] obj) {
		try {
			Page<X> pi = new Page<X>();
			if (limit == 0)
				limit = Constans.DEFAULT_PAGE_SIZE;
			pi.setTotalCount(this.pagingFindCount(sql, obj));
			pi.setResult((List<X>) this.pagingFindList(sql, start, limit,
					rowMapper, obj));
			return pi;
		} catch (RuntimeException e) {
			this.logger.error("JDBC分页查询时出错！");
			throw e;
		}

	}

	/**
	 * 方法 pagingFindList
	 * 
	 * @param sql
	 * @param start
	 * @param limit
	 * @param rowMapper
	 * @return 分页查询的记录对象
	 */
	@SuppressWarnings("unchecked")
	public <X> List<X> pagingFindList(String sql, long start, long limit,
			RowMapper rowMapper) {
		return pagingFindList(sql, start, limit, rowMapper, null);

	}

	/**
	 * 
	 * @param sql
	 * @param start
	 * @param limit
	 * @param rowMapper
	 * @param obj
	 * @return 分页查询的记录对象(单一条件查询)
	 */
	@SuppressWarnings("unchecked")
	public <X> List<X> pagingFindList(String sql, long start, long limit,
			RowMapper rowMapper, Object obj) {
		return (List<X>) pagingFindList(sql, start, limit, rowMapper,
				new Object[] { obj });

	}

	/**
	 * 方法 pagingFindList
	 * 
	 * @param sql
	 * @param start
	 * @param limit
	 * @param rowMapper
	 * @param obj
	 * @return 条件查询分页查询的记录对象
	 */
	@SuppressWarnings("unchecked")
	public <X> List<X> pagingFindList(String sql, long start, long limit,
			RowMapper rowMapper, Object[] obj) {
		try {
			String newSql = this.parseSql(sql).toString();
			List<Object> list = new ArrayList();
			if (obj != null) {
				for (int i = 0; i < obj.length; i++) {
					list.add(obj[i]);
				}
			}
			list.add(start + limit);
			list.add(start);

			return (List<X>) super.getJdbcTemplate().query(newSql,
					list.toArray(), rowMapper);

		} catch (RuntimeException e) {
			this.logger.error("JDBC分页查询，查询分页对象时出错！");
			throw e;
		}
	}

	// sql 语句添加条件
	private String parseSql(String sql) {
		// sql = sql.toLowerCase();
		StringBuffer newsql = new StringBuffer("");

		// String field = sql.substring(fieldstart, fieldend);

		newsql.append(" select * ");
		// newsql.append(field);
		newsql.append(" from (");
		newsql.append(" select pagetable.*");
		// newsql.append(field);
		newsql.append(", rownum rn  from ( ");
		newsql.append(sql);
		newsql.append(" \n) pagetable where rownum<= ? ) where rn > ? ");

		logger.debug("new sql=" + newsql);
		return newsql.toString();
	}

	/**
	 * 方法 pagingFindCount
	 * 
	 * @param sql
	 * @return 该sql语句能查询到的记录总数
	 */
	public long pagingFindCount(String sql) {
		return pagingFindCount(sql, new Object[] {});
	}

	/**
	 * 方法 pagingFindCount
	 * 
	 * @param sql
	 * @param obj
	 * @return 该sql语句能查询到的记录总数
	 */
	public long pagingFindCount(String sql, Object obj) {
		return pagingFindCount(sql, new Object[] { obj });
	}

	/**
	 * 方法 pagingFindCount
	 * 
	 * @param sql
	 * @param obj
	 * @return 条件查询记录总数
	 */
	public long pagingFindCount(String sql, Object[] obj) {
		try {
			// String newSql = " select count(1) "
			// + sql.substring(sql.toLowerCase().indexOf("from"));
			String newSql = "select count(1) from ( " + sql + "\n ) ";
			logger.debug("new count sql =" + newSql);
			return super.getJdbcTemplate().queryForLong(newSql, obj);
		} catch (RuntimeException e) {
			this.logger.error("JDBC分页查询，查询记录总数时出错！");
			throw e;
		}
	}

	// -------------------------------------------------------------------
	// 以下为实现 JdbcTemplate 的方法

	public int[] batchUpdate(String sql, BatchPreparedStatementSetter pss)
			throws DataAccessException {

		return super.getJdbcTemplate().batchUpdate(sql, pss);
	}

	public int[] batchUpdate(String[] sql) throws DataAccessException {

		return super.getJdbcTemplate().batchUpdate(sql);
	}

	public Map<String, Object> call(CallableStatementCreator csc,
			List<SqlParameter> declaredParameters) throws DataAccessException {

		return super.getJdbcTemplate().call(csc, declaredParameters);
	}

	public <T> T execute(CallableStatementCreator csc,
			CallableStatementCallback<T> action) throws DataAccessException {

		return super.getJdbcTemplate().execute(csc, action);
	}

	public <T> T execute(ConnectionCallback<T> action)
			throws DataAccessException {

		return super.getJdbcTemplate().execute(action);
	}

	public <T> T execute(PreparedStatementCreator psc,
			PreparedStatementCallback<T> action) throws DataAccessException {

		return super.getJdbcTemplate().execute(psc, action);
	}

	public <T> T execute(StatementCallback<T> action)
			throws DataAccessException {

		return super.getJdbcTemplate().execute(action);
	}

	public <T> T execute(String callString, CallableStatementCallback<T> action)
			throws DataAccessException {

		return super.getJdbcTemplate().execute(callString, action);
	}

	public <T> T execute(String sql, PreparedStatementCallback<T> action)
			throws DataAccessException {

		return super.getJdbcTemplate().execute(sql, action);
	}

	public void execute(String sql) throws DataAccessException {

		super.getJdbcTemplate().execute(sql);
	}

	public int getFetchSize() {

		return super.getJdbcTemplate().getFetchSize();
	}

	public int getMaxRows() {

		return super.getJdbcTemplate().getMaxRows();
	}

	public NativeJdbcExtractor getNativeJdbcExtractor() {

		return super.getJdbcTemplate().getNativeJdbcExtractor();
	}

	public int getQueryTimeout() {

		return super.getJdbcTemplate().getQueryTimeout();
	}

	public boolean isIgnoreWarnings() {

		return super.getJdbcTemplate().isIgnoreWarnings();
	}

	public boolean isResultsMapCaseInsensitive() {

		return super.getJdbcTemplate().isResultsMapCaseInsensitive();
	}

	public boolean isSkipResultsProcessing() {

		return super.getJdbcTemplate().isSkipResultsProcessing();
	}

	public boolean isSkipUndeclaredResults() {

		return super.getJdbcTemplate().isSkipUndeclaredResults();
	}

	public <T> T query(PreparedStatementCreator psc,
			PreparedStatementSetter pss, ResultSetExtractor<T> rse)
			throws DataAccessException {

		return super.getJdbcTemplate().query(psc, pss, rse);
	}

	public <T> T query(PreparedStatementCreator psc, ResultSetExtractor<T> rse)
			throws DataAccessException {

		return super.getJdbcTemplate().query(psc, rse);
	}

	public void query(PreparedStatementCreator psc, RowCallbackHandler rch)
			throws DataAccessException {

		super.getJdbcTemplate().query(psc, rch);
	}

	public <T> List<T> query(PreparedStatementCreator psc,
			RowMapper<T> rowMapper) throws DataAccessException {

		return super.getJdbcTemplate().query(psc, rowMapper);
	}

	public <T> T query(String sql, Object[] args, int[] argTypes,
			ResultSetExtractor<T> rse) throws DataAccessException {

		return super.getJdbcTemplate().query(sql, args, argTypes, rse);
	}

	public void query(String sql, Object[] args, int[] argTypes,
			RowCallbackHandler rch) throws DataAccessException {

		super.getJdbcTemplate().query(sql, args, argTypes, rch);
	}

	public <T> List<T> query(String sql, Object[] args, int[] argTypes,
			RowMapper<T> rowMapper) throws DataAccessException {

		return super.getJdbcTemplate().query(sql, args, argTypes, rowMapper);
	}

	public <T> T query(String sql, Object[] args, ResultSetExtractor<T> rse)
			throws DataAccessException {

		return super.getJdbcTemplate().query(sql, args, rse);
	}

	public void query(String sql, Object[] args, RowCallbackHandler rch)
			throws DataAccessException {

		super.getJdbcTemplate().query(sql, args, rch);
	}

	public <T> List<T> query(String sql, Object[] args, RowMapper<T> rowMapper)
			throws DataAccessException {

		return super.getJdbcTemplate().query(sql, args, rowMapper);
	}

	public <T> T query(String sql, PreparedStatementSetter pss,
			ResultSetExtractor<T> rse) throws DataAccessException {

		return super.getJdbcTemplate().query(sql, pss, rse);
	}

	public void query(String sql, PreparedStatementSetter pss,
			RowCallbackHandler rch) throws DataAccessException {

		super.getJdbcTemplate().query(sql, pss, rch);
	}

	public <T> List<T> query(String sql, PreparedStatementSetter pss,
			RowMapper<T> rowMapper) throws DataAccessException {

		return super.getJdbcTemplate().query(sql, pss, rowMapper);
	}

	public <T> T query(String sql, ResultSetExtractor<T> rse, Object... args)
			throws DataAccessException {

		return super.getJdbcTemplate().query(sql, rse, args);
	}

	public <T> T query(String sql, ResultSetExtractor<T> rse)
			throws DataAccessException {

		return super.getJdbcTemplate().query(sql, rse);
	}

	public void query(String sql, RowCallbackHandler rch, Object... args)
			throws DataAccessException {

		super.getJdbcTemplate().query(sql, rch, args);
	}

	public void query(String sql, RowCallbackHandler rch)
			throws DataAccessException {

		super.getJdbcTemplate().query(sql, rch);
	}

	public <T> List<T> query(String sql, RowMapper<T> rowMapper, Object... args)
			throws DataAccessException {

		return super.getJdbcTemplate().query(sql, rowMapper, args);
	}

	public <T> List<T> query(String sql, RowMapper<T> rowMapper)
			throws DataAccessException {

		return super.getJdbcTemplate().query(sql, rowMapper);
	}

	public int queryForInt(String sql, Object... args)
			throws DataAccessException {

		return super.getJdbcTemplate().queryForInt(sql, args);
	}

	public int queryForInt(String sql, Object[] args, int[] argTypes)
			throws DataAccessException {

		return super.getJdbcTemplate().queryForInt(sql, args, argTypes);
	}

	public int queryForInt(String sql) throws DataAccessException {

		return super.getJdbcTemplate().queryForInt(sql);
	}

	public <T> List<T> queryForList(String sql, Class<T> elementType,
			Object... args) throws DataAccessException {

		return super.getJdbcTemplate().queryForList(sql, elementType, args);
	}

	public <T> List<T> queryForList(String sql, Class<T> elementType)
			throws DataAccessException {

		return super.getJdbcTemplate().queryForList(sql, elementType);
	}

	public List<Map<String, Object>> queryForList(String sql, Object... args)
			throws DataAccessException {

		return super.getJdbcTemplate().queryForList(sql, args);
	}

	public <T> List<T> queryForList(String sql, Object[] args,
			Class<T> elementType) throws DataAccessException {

		return super.getJdbcTemplate().queryForList(sql, args, elementType);
	}

	public <T> List<T> queryForList(String sql, Object[] args, int[] argTypes,
			Class<T> elementType) throws DataAccessException {

		return super.getJdbcTemplate().queryForList(sql, args, argTypes,
				elementType);
	}

	public List<Map<String, Object>> queryForList(String sql, Object[] args,
			int[] argTypes) throws DataAccessException {

		return super.getJdbcTemplate().queryForList(sql, args, argTypes);
	}

	public List<Map<String, Object>> queryForList(String sql)
			throws DataAccessException {

		return super.getJdbcTemplate().queryForList(sql);
	}

	public long queryForLong(String sql, Object... args)
			throws DataAccessException {

		return super.getJdbcTemplate().queryForLong(sql, args);
	}

	public long queryForLong(String sql, Object[] args, int[] argTypes)
			throws DataAccessException {

		return super.getJdbcTemplate().queryForLong(sql, args, argTypes);
	}

	public long queryForLong(String sql) throws DataAccessException {

		return super.getJdbcTemplate().queryForLong(sql);
	}

	public Map<String, Object> queryForMap(String sql, Object... args)
			throws DataAccessException {

		return super.getJdbcTemplate().queryForMap(sql, args);
	}

	public Map<String, Object> queryForMap(String sql, Object[] args,
			int[] argTypes) throws DataAccessException {

		return super.getJdbcTemplate().queryForMap(sql, args, argTypes);
	}

	public Map<String, Object> queryForMap(String sql)
			throws DataAccessException {

		return super.getJdbcTemplate().queryForMap(sql);
	}

	public <T> T queryForObject(String sql, Class<T> requiredType,
			Object... args) throws DataAccessException {

		return super.getJdbcTemplate().queryForObject(sql, requiredType, args);
	}

	public <T> T queryForObject(String sql, Class<T> requiredType)
			throws DataAccessException {

		return super.getJdbcTemplate().queryForObject(sql, requiredType);
	}

	public <T> T queryForObject(String sql, Object[] args, Class<T> requiredType)
			throws DataAccessException {

		return super.getJdbcTemplate().queryForObject(sql, args, requiredType);
	}

	public <T> T queryForObject(String sql, Object[] args, int[] argTypes,
			Class<T> requiredType) throws DataAccessException {

		return super.getJdbcTemplate().queryForObject(sql, args, argTypes,
				requiredType);
	}

	public <T> T queryForObject(String sql, Object[] args, int[] argTypes,
			RowMapper<T> rowMapper) throws DataAccessException {

		return super.getJdbcTemplate().queryForObject(sql, args, argTypes,
				rowMapper);
	}

	public <T> T queryForObject(String sql, Object[] args,
			RowMapper<T> rowMapper) throws DataAccessException {

		return super.getJdbcTemplate().queryForObject(sql, args, rowMapper);
	}

	public <T> T queryForObject(String sql, RowMapper<T> rowMapper,
			Object... args) throws DataAccessException {

		return super.getJdbcTemplate().queryForObject(sql, rowMapper, args);
	}

	public <T> T queryForObject(String sql, RowMapper<T> rowMapper)
			throws DataAccessException {

		return super.getJdbcTemplate().queryForObject(sql, rowMapper);
	}

	public SqlRowSet queryForRowSet(String sql, Object... args)
			throws DataAccessException {

		return super.getJdbcTemplate().queryForRowSet(sql, args);
	}

	public SqlRowSet queryForRowSet(String sql, Object[] args, int[] argTypes)
			throws DataAccessException {

		return super.getJdbcTemplate().queryForRowSet(sql, args, argTypes);
	}

	public SqlRowSet queryForRowSet(String sql) throws DataAccessException {

		return super.getJdbcTemplate().queryForRowSet(sql);
	}

	public void setFetchSize(int fetchSize) {

		super.getJdbcTemplate().setFetchSize(fetchSize);
	}

	public void setIgnoreWarnings(boolean ignoreWarnings) {

		super.getJdbcTemplate().setIgnoreWarnings(ignoreWarnings);
	}

	public void setMaxRows(int maxRows) {

		super.getJdbcTemplate().setMaxRows(maxRows);
	}

	public void setNativeJdbcExtractor(NativeJdbcExtractor extractor) {

		super.getJdbcTemplate().setNativeJdbcExtractor(extractor);
	}

	public void setQueryTimeout(int queryTimeout) {

		super.getJdbcTemplate().setQueryTimeout(queryTimeout);
	}

	public void setResultsMapCaseInsensitive(boolean resultsMapCaseInsensitive) {

		super.getJdbcTemplate().setResultsMapCaseInsensitive(
				resultsMapCaseInsensitive);
	}

	public void setSkipResultsProcessing(boolean skipResultsProcessing) {

		super.getJdbcTemplate().setSkipResultsProcessing(skipResultsProcessing);
	}

	public void setSkipUndeclaredResults(boolean skipUndeclaredResults) {

		super.getJdbcTemplate().setSkipUndeclaredResults(skipUndeclaredResults);
	}

	public int update(PreparedStatementCreator psc, KeyHolder generatedKeyHolder)
			throws DataAccessException {

		return super.getJdbcTemplate().update(psc, generatedKeyHolder);
	}

	public int update(PreparedStatementCreator psc) throws DataAccessException {

		return super.getJdbcTemplate().update(psc);
	}

	public int update(String sql, Object... args) throws DataAccessException {

		return super.getJdbcTemplate().update(sql, args);
	}

	public int update(String sql, Object[] args, int[] argTypes)
			throws DataAccessException {

		return super.getJdbcTemplate().update(sql, args, argTypes);
	}

	public int update(String sql, PreparedStatementSetter pss)
			throws DataAccessException {

		return super.getJdbcTemplate().update(sql, pss);
	}

	public int update(String sql) throws DataAccessException {

		return super.getJdbcTemplate().update(sql);
	}

}
